home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
130_01
/
disku.c
< prev
next >
Wrap
Text File
|
1985-03-09
|
17KB
|
620 lines
/*
DISK UTILITY PROGRAM
Written by Richard Damon
Version 1.0 May 1980
Revised by Bob Pasky
Version 2.0 July 1981
Version 2.4 Oct. 1981
This program allows the operator to examine and modify
a CPM diskette, either single density or Micromation's version of
double density.
The commands available in this package are :
Tn set current track to n (0-76)
Sn set current sector to n (1-26/52)
Ln set current logical sector to n (0-25/51)
Dn set current disk number to n (0-3)
Bn set current track and sector to point to block n (0-F2)
N set current track and sector to next sector/block
next sector if last set command was for track or sector
next block if last set command was for block
I increment sector, if sector>max set to 1 and increment track
R read sector/block into buffer
W write sector/block from buffer
P print out contents of buffer, along with track/sector/block information
Ea n n n n
edit buffer starting from location a filling with values n n n
Aa "ccc..."
edit buffer starting from location a with ascii characters ccc...
Fn fill buffer with value n
X exit program
M print disk allocation map
Cn collate directory: n=0 orders by file type (from typtbl), n=1 by name
? prints current track, sector, block info
/ repeats last command string
Notes:
1) Multiple commands may be specified on a line except for X and /
which must be the only command on the line followed by return.
2) Commands may be in upper or lower case letters
3) Spaces are ignored except in the E command where they are used
as separaters for the numbers
Typical commands:
d0t0s1rp read in the track 0 sector 1 of disk 0 (Drive A) and print it
e1A 4F 20 11 set buffer location 1A to 4F, 1B to 20, and 1C to 11.
e0a 00w set buffer location 0a to 0 and write buffer
Note no space after last data byte
nrp get next buffer and print it
Disk Allocation Map
The M command is designed to allow the directory blocks (blocks 0 and 1)
to be printed out in a convient format. The directory is print out in the
following format:
Section 1:
The top half of the directory listing is a listing of the name
inforamtion of the directory entries. Each line corresponds to 1 sector
of the directory. A typical entry would be f=DISKTESTCOM/1 4c
The first letter is a code letter used to referance into section 2.
The equal sign indicats that the file exists, a star here indicates
that this entry is a deleted file.
Next comes the filename and extension.
The following /n is printed if this is other then the first extent
(extent 0) of a file where n is the extent number of this entry.
The following number is the hex record count for this extent.
Section 2:
The bottom half of the directory listing is a disk allocation map
showing which blocks are in use and by which file. Free blocks are
indicated by a dot while used blocks are marked by the file control
letter asigned to a file in section 1. This listing has been blocked off
in groups of 8 and 16 to ease reading.
DIRECTORY SORTING
Collating (sorting) the directory only places the sorted directory
in the buffer. From there you can Write it back to the disk if desired,
producing a sorted directory on the disk. The track, sector and block size
are set up by Collate to their proper values for writing to the directory.
Sorting can be performed alphabetically by the full name, type and
extent, or grouped by type using a table within this program to sort by
type -- within each type the files are ordered by name and extent. File
types not found in the table are placed at the end, arranged by name, type
and extent.
CPM FILE STRUCTURE
To help the user of this program the following is a brief description
of the format used in CPM. (Double density values are shown in parentheses.)
The first 2 tracks of a disk are reserved for the bootstrap and the copy of
the CPM operating system. Tracks 2 through 76 store the data. To speed up
disk access CPM does not store consecutive data in consecutive sectors.
Instead it uses every (8th or) 6th sector for data. Thus to read logical
consecutive sectors you must read the sectors in the following order:
(single density only)
1 7 13 19 25 5 11 17 23 3 9 15 21 2 8 14 20 26 6 12 18 24 4 10 16 22
This interleaving is taken care of when reading in multiple sectors
or when incrementing the disk address with the N command. To simplify
the disk allocation scheme the sectors are the collected into groups of
(16 or) 8 sectors forming a (2k or) 1k block. These blocks are numbered
from 0 starting with the beginning of the directory -- track 2 sector 1.
Block numbers range from 0 to F2 (hex).
The directory is organized to use (1 or) 2 blocks of storage -- 16
sectors -- to store information on 64 file extensions. A file extension
is a part of a file up to 16k bytes long. The directory entry for a file
extension is as follows:
byte 0 : file code : 0 if file exists, E5 if file is deleted
byte 1- 8: file name : ascii representation of file name
byte 9-11: file type : ascii representation of file type
byte 12 : file ext : binary number for extent number (0 to ?)
byte 13,14: unused
byte 15 : rec count : count of number of sectors in extent
byte 16-31: map : list of block numbers used by this extent
*/
#include <bdscio.h>
#define MAXTYP 14 /* how many file types to sort on */
#define SORTED '~' /* this may need changing for CP/M 2.x;
anything not seen in file_code is ok */
#define DELETED 0xe5 /* ...anything except E5, of course */
#define ESCAPE 0x1b
#define STRDLM '"'
int DEBUG;
int maxsecs, blocksecs, interval, typ, presdisk;
char density, buffer[2048], dir[2048], map[256];
STATIC_char *typtbl[MAXTYP];
main(ac,av)
int ac;
char **av;
{
int track, sector, disk, nsect, s, t, rs, rt, i, j, k, block;
char buff[80], prevbuff[80], *bufp, c, d, mc;
disk=0;
track=rt=rs=0;
sector=1;
nsect=1;
DEBUG = 0;
if (ac > 1 && (*av[1] == 'D')) DEBUG = 1;
if(DEBUG)printf("\nDebug on...\n");
presdisk = bdos(25,0); /* find out which disk called from */
typtbl[0]="COM"; /* change this table as desired */
typtbl[1]="SUB";
typtbl[2]="CRL";
typtbl[3]="CCC";
typtbl[4]="H ";
typtbl[5]="C ";
typtbl[6]=" ";
typtbl[7]="HEX";
typtbl[8]="DOC";
typtbl[9]="TXT";
typtbl[10]="BAK";
typtbl[11]="BRL";
typtbl[12]="TMP";
typtbl[13]="BAD"; /* note that the typtbl vector contains
only pointers to the strings
********/
printf("\n\t\tDisk Utility v 2.4\n");
printf("Density on %c is Double\n", presdisk+65);
maxsecs = 52;
blocksecs = 16;
interval = 8;
prevbuff[0] = '\0'; /* init last command string to nil */
printf("Command? ");
while(tolower(*(bufp=gets(buff))) != 'x' || *(bufp+1) != '\0'){
if((*bufp == '/') && (*(bufp+1) == '\0'))
strcpy(buff,prevbuff);
strcpy(prevbuff,buff); /* save last command string */
while((c=*bufp++) != '\0')
switch(toupper(c)){
case 'T' : track=getnum(&bufp,0,76,10,'T',track);
nsect=1;
break;
case 'S' : sector=getnum(&bufp,1,maxsecs,10,'S',
sector);
nsect=1;
break;
case 'L' : s=getnum(&bufp,0,maxsecs-1,10,'L',
tolog(sector));
sector = tophys(s);
nsect=1;
break;
case 'D' : disk=getnum(&bufp,0,3,10,'D',presdisk);
do {
printf("\nDensity of %c? (s/d) ", disk+65);
density = tolower(getchar());
} while (density != 's' && density != 'd');
if (density == 's') {
printf("ingle\n");
maxsecs = 26;
blocksecs = 8;
interval = 6;
}
else {
printf("ouble\n");
maxsecs = 52;
blocksecs = 16;
interval = 8;
}
break;
case 'B' : block=getnum(&bufp,0,0xf2,16,'B',block);
nsect=blocksecs;
track=2 + block*blocksecs / maxsecs;
s = block*blocksecs % maxsecs;
sector = tophys(s);
break;
case 'N' : for(i=0;i<nsect;i++){
sector = bumpsector(sector);